<template></template>

<script setup>
import { onBeforeUnmount, onMounted, nextTick } from 'vue';
import { getArea, getLength } from 'ol/sphere';
import 'ol/ol.css';
import { onBeforeRouteUpdate } from 'vue-router';
import { storeToRefs } from 'pinia';
import { useMap } from '@/stores/useMap.js';

let source, vector;
let drawType;
var listener = null;
var sketch;
let continuePolygonMsg = '单击此处绘制多边形'; // 绘制面提示文字
let continueLineMsg = '单击此处绘制线'; // 绘制线提示文字
let helpTooltipElement; // 帮助提示框元素
let helpTooltip;
var measureTooltipElement;
var measureTooltip;
const { map, draw } = storeToRefs(useMap());
const { setDraw } = useMap();

onMounted(async () => {
  await nextTick(); // 确保 DOM 更新完成
  // 创建图层
  source = new ol.source.Vector(); // 图层数据源
  vector = new ol.layer.Vector({
    source: source,
  });
});

// 鼠标移动函数，展示提示文字
var pointerMoveHandler = function (evt) {
  if (evt.dragging) {
    return;
  }
  let helpMsg = '点击开始绘制';
  if (sketch) {
    // 测量时的提示文字
    const geom = sketch.getGeometry();
    if (geom instanceof ol.geom.Polygon) {
      helpMsg = continuePolygonMsg;
    } else if (geom instanceof ol.geom.LineString) {
      helpMsg = continueLineMsg;
    }
  }
  // 设置提示对话框
  helpTooltipElement.innerHTML = helpMsg;
  helpTooltip.setPosition(evt.coordinate);
  helpTooltipElement.classList.remove('hidden');
};

// 创建帮助提示框元素
function createHelpTooltip() {
  if (helpTooltipElement) {
    // 在移除之前检查元素是否存在
    if (helpTooltipElement.parentNode) {
      helpTooltipElement.parentNode.removeChild(helpTooltipElement);
    }
  }
  helpTooltipElement = document.createElement('div');
  helpTooltipElement.className = 'ol-tooltip hidden';
  helpTooltip = new ol.Overlay({
    element: helpTooltipElement,
    offset: [15, 0],
    positioning: 'center-left',
  });
  map.value.addOverlay(helpTooltip);
}

// 创建测量提示元素
function createMeasureTooltip() {
  // 如已经有了则移除
  if (measureTooltipElement) {
    // 在移除之前检查元素是否存在
    if (measureTooltipElement.parentNode) {
      measureTooltipElement.parentNode.removeChild(measureTooltipElement);
    }
  }
  // 创建 div，new 一个 Overlay 对象，div 作为 element 的属性值
  measureTooltipElement = document.createElement('div');
  measureTooltipElement.className = 'ol-tooltip ol-tooltip-measure';
  measureTooltip = new ol.Overlay({
    element: measureTooltipElement,
    offset: [0, -15],
    positioning: 'bottom-center',
  });
  map.value.addOverlay(measureTooltip);
}

function initDraw() {
  // 每次初始化绘制时移除之前的交互
  if (draw.value) {
    map.value.removeInteraction(draw.value);
  }
  // 创建新的绘制交互对象
  const newDraw = new ol.interaction.Draw({
    source: source,
    type: drawType,
  });
  // 添加绘制交互
  map.value.addInteraction(newDraw);
  setDraw(newDraw); // 更新 draw 状态

  createHelpTooltip();
  createMeasureTooltip();
  // 监听鼠标移动
  map.value.on('pointermove', pointerMoveHandler);
  // 鼠标移出，隐藏样式
  map.value.getViewport().addEventListener('mouseout', function () {
    helpTooltipElement.classList.add('hidden');
  });
  // 监听绘制事件
  newDraw.on('drawstart', evt => {
    sketch = evt.feature;
    var tooltipCoord = evt.coordinate;
    listener = sketch.getGeometry().on('change', function (evt) {
      var geom = evt.target; // 绘制几何要素
      var output;
      if (geom instanceof ol.geom.Polygon) {
        output = formatArea(geom); // 面积值
        // tooltipCoord = geom.getInteriorPoint().getCoordinates() // 坐标
      } else if (geom instanceof ol.geom.LineString) {
        output = formatLength(geom);
      }
      tooltipCoord = geom.getLastCoordinate(); // 设置鼠标位置改变后的实时位置
      measureTooltipElement.innerHTML = output; // 设置提示框的内容，就是距离
      measureTooltip.setPosition(tooltipCoord);
    });
  });
  newDraw.on('drawend', e => {
    measureTooltipElement.className = 'ol-tooltip ol-tooltip-static';
    measureTooltip.setOffset([0, -7]);
    // 清空要素和提示框
    sketch = null;
    measureTooltipElement = null;
    // 创建展示结果
    createMeasureTooltip();
  });
}

onBeforeRouteUpdate(to => {
  // 接收路由参数的变化
  const type = to.params.measureType;
  // 关闭测量，移除绘制交互并清空图层
  if (type === 'close') {
    if (helpTooltipElement && helpTooltipElement.parentNode) {
      helpTooltipElement.parentNode.removeChild(helpTooltipElement);
    }
    if (measureTooltipElement && measureTooltipElement.parentNode) {
      measureTooltipElement.parentNode.removeChild(measureTooltipElement);
    }
    map.value.getOverlays().clear();
    if (draw.value) {
      map.value.removeInteraction(draw.value);
    }
    source.clear();
    return;
  }

  if (type === 'distance') {
    map.value.addLayer(vector); // 添加图层
    drawType = 'LineString';
    initDraw();
  }
  if (type === 'area') {
    map.value.addLayer(vector); // 添加图层
    drawType = 'Polygon';
    initDraw();
  }
  if (type === 'export') {
    MapExportPng();
  }
});

onBeforeUnmount(() => {
  // 清理资源
  map.value.removeInteraction(draw.value);
  map.value.getOverlays().clear();
  source.clear();
});

// 测量距离
var formatLength = function (line) {
  var sourceProj = map.value.getView().getProjection(); // 获取投影坐标系
  var length = getLength(line, {
    projection: sourceProj,
  });
  var output;
  if (length > 100) {
    output = Math.round((length / 1000) * 100) / 100 + ' ' + 'km';
  } else {
    output = Math.round(length * 100) / 100 + ' ' + 'm';
  }
  return output;
};

// 测量面积
var formatArea = function (polygon) {
  var sourceProj = map.value.getView().getProjection(); // 获取投影坐标系
  var area = getArea(polygon, {
    projection: sourceProj,
  });
  var output;
  if (area > 10000) {
    output = Math.round((area / 1000000) * 100) / 100 + ' ' + 'km<sup>2</sup>'; // 换算成 KM 单位
  } else {
    output = Math.round(area * 100) / 100 + ' ' + 'm<sup>2</sup>'; // m 为单位
  }
  return output; // 返回多边形的面积
};

// 导出图片
function MapExportPng() {
  map.value.once('rendercomplete', function (event) {
    var canvas = map.value.getTargetElement().querySelector('canvas'); // 获取地图的 canvas 元素
    canvas.setAttribute('crossOrigin', 'anonymous'); // 允许跨域
    if (canvas) {
      // 使用 canvas 对象进行操作，例如打印或导出
      console.log(canvas);
      var link = document.createElement('a');
      link.setAttribute('download', 'map.png');
      link.href = canvas.toDataURL('image/png');
      link.click();
    } else {
      console.error('无法找到 Canvas 元素');
    }
  });
  map.value.renderSync();
}
</script>

<style scoped>
.hidden {
  display: none;
}
</style>
